﻿using Flurl.Http;
using Jupiter.Infrastructure;
using Jupiter.Infrastructure.Responses;
using MediatR;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Wips.Domain.Events;
using Wips.Domain.Models;
using Wips.Infrastructure.Helpers;
using Wips.Infrastructure.Model;
using Wips.Infrastructure.Options;

namespace Wips.AppService.SqlSugar
{
    /// <summary>
    ///
    /// </summary>
    public class PublishMasterService
    {
        private readonly IConfiguration _configuration;
        private readonly AuthConfig? _authConfig;
        private readonly IMediator _mediator;

        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="mediator"></param>
        /// <exception cref="Exception"></exception>
        public PublishMasterService(IConfiguration configuration, IMediator mediator)
        {
            _configuration = configuration;
            _authConfig = _configuration.GetSection("AuthConfig").Get<AuthConfig>();
            if (_authConfig == null)
            {
                throw new Exception("AuthConfig not config");
            }

            _mediator = mediator;
        }

        /// <summary>
        /// 添加日志
        /// </summary>
        /// <param name="logEvent"></param>
        /// <returns></returns>
        public async Task ExecuteWithLogging(AddPublishLogEvent logEvent)
        {
            // 发布日志事件
            await _mediator.Publish(logEvent);
        }

        /// <summary>
        /// 发布
        /// </summary>
        /// <param name="agentAddress"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> PublishAsync(string agentAddress, PublishRequest request)
        {
            var log = new AddPublishLogEvent(request, EnumNodeType.Publish);
            log.Context = JsonConvert.SerializeObject(request);
            try
            {
                var result = await (agentAddress + Wips.Infrastructure.Consts.MapPublish)
                    .WithTimeout(60)
                    .WithHeader("sign",
                        Rsa2Helper.EncryptWithPublicKey(
                            Wips.Infrastructure.Consts.MapPublish + JsonConvert.SerializeObject(request),
                            _authConfig!.PublicKey))
                    .PostJsonAsync(request)
                    .ReceiveJson<ApiResult<string>>();
                log.Result = JsonConvert.SerializeObject(result);
                return result;
            }
            catch (Exception ex)
            {
                log.Result = ex.Message;
                throw;
            }
            finally
            {
                await ExecuteWithLogging(log);
            }
        }


        /// <summary>
        /// 还原
        /// </summary>
        /// <param name="agentAddress"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> RestoreAsync(string agentAddress, PublishRequest request)
        {
            var log = new AddPublishLogEvent(request, EnumNodeType.Restore);
            log.Context = JsonConvert.SerializeObject(request);
            try
            {
                var result = await (agentAddress + Wips.Infrastructure.Consts.MapPublish)
                    .WithTimeout(60)
                    .WithHeader("sign",
                        Rsa2Helper.EncryptWithPublicKey(
                            Wips.Infrastructure.Consts.MapPublish + JsonConvert.SerializeObject(request),
                            _authConfig!.PublicKey))
                    .PostJsonAsync(request)
                    .ReceiveJson<ApiResult<string>>();
                log.Result = JsonConvert.SerializeObject(result);
                return result;
            }
            catch (Exception ex)
            {
                log.Result = ex.Message;
                throw;
            }
            finally
            {
                await ExecuteWithLogging(log);
            }
        }

        /// <summary>
        /// 执行脚本
        /// </summary>
        /// <param name="agentAddress"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> RunScriptAsync(string agentAddress, RunScriptRequest request)
        {
            var command = request.Command.Split(' ');
            foreach (var item in command)
            {
                if (Wips.Infrastructure.Consts.NotSupportCommand.Where(c => c.ToLower().StartsWith(item.ToLower()))
                    .Any())
                {
                    throw new Exception("不支持的命令");
                }

                if (Wips.Infrastructure.Consts.NotSupportKeyWord.Where(c => item.ToLower().Contains(c.ToLower())).Any())
                {
                    throw new Exception("不支持的关键字");
                }
            }

            var log = new AddPublishLogEvent(request, EnumNodeType.RunScript);
            log.Context = JsonConvert.SerializeObject(request);
            try
            {
                var result = await (agentAddress + Wips.Infrastructure.Consts.MapRunScript)
                    .WithTimeout(60)
                    .WithHeader("sign",
                        Rsa2Helper.EncryptWithPublicKey(
                            Wips.Infrastructure.Consts.MapRunScript + JsonConvert.SerializeObject(request),
                            _authConfig!.PublicKey))
                    .PostJsonAsync(request)
                    .ReceiveJson<ApiResult<string>>();
                log.Result = JsonConvert.SerializeObject(result);
                return result;
            }
            catch (Exception ex)
            {
                log.Result = ex.Message;
                throw;
            }
            finally
            {
                await ExecuteWithLogging(log);
            }
        }

        /// <summary>
        /// 获取zip里面的文件目录
        /// </summary>
        /// <param name="agentAddress"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public async Task<ApiResult<List<DirectoryModel>>> GetZipFileInfoListAsync(string agentAddress, string path)
        {
            var param = "path=" + path;
            var result = await (agentAddress + Wips.Infrastructure.Consts.MapGetZipFileInfoList)
                .WithTimeout(30)
                .WithHeader("sign",
                    Rsa2Helper.EncryptWithPublicKey(Wips.Infrastructure.Consts.MapGetZipFileInfoList + param,
                        _authConfig!.PublicKey))
                .SetQueryParam("path", path)
                .GetJsonAsync<ApiResult<List<DirectoryModel>>>();
            return result;
        }


        /// <summary>
        /// 健康检查
        /// </summary>
        /// <param name="agentAddress"></param>
        /// <returns></returns>
        public async Task<string> HealthyCheckAsync(string agentAddress)
        {
            return await (agentAddress + Wips.Infrastructure.Consts.MapHealthCheckPath)
                .WithHeader("sign",
                    Rsa2Helper.EncryptWithPublicKey(Wips.Infrastructure.Consts.MapHealthCheckPath,
                        _authConfig!.PublicKey))
                .WithTimeout(5).GetAsync().ReceiveString();
        }

        /// <summary>
        /// 获取盘符数据
        /// </summary>
        /// <param name="agentAddress"></param>
        /// <returns></returns>
        public async Task<ApiResult<List<string>>> GetRootPathAsync(string agentAddress)
        {
            var result = await (agentAddress + Wips.Infrastructure.Consts.MapGetRootPath)
                .WithHeader("sign",
                    Rsa2Helper.EncryptWithPublicKey(Wips.Infrastructure.Consts.MapGetRootPath, _authConfig!.PublicKey))
                .WithTimeout(5).GetJsonAsync<ApiResult<List<string>>>();
            return result;
        }


        /// <summary>
        /// 获取文件夹列表
        /// </summary>
        /// <param name="agentAddress"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public async Task<ApiResult<List<DirectoryModel>>> GetFolderListAsync(string agentAddress, string path)
        {
            var param = "path=" + path;
            var result = await (agentAddress + Wips.Infrastructure.Consts.MapGetFolderListPath)
                .WithTimeout(30)
                .WithHeader("sign",
                    Rsa2Helper.EncryptWithPublicKey(Wips.Infrastructure.Consts.MapGetFolderListPath + param,
                        _authConfig!.PublicKey))
                .SetQueryParam("path", path)
                .GetJsonAsync<ApiResult<List<DirectoryModel>>>();
            return result;
        }


        /// <summary>
        /// 执行备份
        /// </summary>
        /// <param name="agentAddress"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> BackUpAsync(string agentAddress, BackupRequest request)
        {
            var log = new AddPublishLogEvent(request, EnumNodeType.BackUp);
            log.Context = JsonConvert.SerializeObject(request);
            try
            {
                var sign = Rsa2Helper.EncryptWithPublicKey(
                    Wips.Infrastructure.Consts.MapAgentBackUpPath + JsonConvert.SerializeObject(request),
                    _authConfig!.PublicKey);

                var result = await (agentAddress + Wips.Infrastructure.Consts.MapAgentBackUpPath)
                    .WithHeader("sign", sign)
                    .WithTimeout(60)
                    .PostJsonAsync(request)
                    .ReceiveJson<ApiResult<string>>();

                log.Result = JsonConvert.SerializeObject(result);
                return result;
            }
            catch (Exception ex)
            {
                log.Result = ex.Message;
                throw;
            }
            finally
            {
                await ExecuteWithLogging(log);
            }
        }


        /// <summary>
        /// 获取文本内容
        /// </summary>
        /// <param name="agentAddress"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        // 获取文件内容
        public async Task<ApiResult<string>> GetFileTextAsync(string agentAddress, string path)
        {
            var param = "path=" + path;
            var result = await (agentAddress + Wips.Infrastructure.Consts.MapGetFileText)
                .WithTimeout(30)
                .WithHeader("sign",
                    Rsa2Helper.EncryptWithPublicKey(Wips.Infrastructure.Consts.MapGetFileText + param,
                        _authConfig!.PublicKey))
                .SetQueryParam("path", path)
                .GetJsonAsync<ApiResult<string>>();
            return result;
        }

        /// <summary>
        /// 保存修改文件内容
        /// </summary>
        /// <param name="agentAddress"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> SaveFileTextAsync(string agentAddress, SaveFileTextRequest request)
        {
            var log = new AddPublishLogEvent(request, EnumNodeType.SaveFile);
            log.Context = JsonConvert.SerializeObject(request);

            request.RollString = ObjectId.GenerateNewStringId();
            var body = request.RollString;

            try
            {
                var sign = Rsa2Helper.EncryptWithPublicKey(Wips.Infrastructure.Consts.MapSaveFileText + body,
                    _authConfig!.PublicKey);

                var result = await (agentAddress + Wips.Infrastructure.Consts.MapSaveFileText)
                    .WithHeader("sign", sign)
                    .WithTimeout(60)
                    .PostJsonAsync(request)
                    .ReceiveJson<ApiResult<string>>();

                log.Result = JsonConvert.SerializeObject(result);
                return result;
            }
            catch (Exception ex)
            {
                log.Result = ex.Message;
                throw;
            }
            finally
            {
                await ExecuteWithLogging(log);
            }
        }
    }
}